package eu.robico.simulator.simulatorinterface.communication;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.StringTokenizer;

import eu.robico.simulator.simulatorinterface.communication.Protocol.Update;
import eu.robico.simulator.simulatorinterface.communication.Protocol.UpdateType;

/**
 * Special note: Communication co-depends on the contract of bufferedReader.readLine()
 * @author Arie
 *
 */
class HostListener extends Thread
{
	private Host host;
	private BufferedReader input;
	private volatile boolean running = true;
	
	public HostListener(Host host, BufferedReader input)
	{
		this.host = host;
		this.input = input;
	}
	
	public void run()
	{
		try 
		{
			boolean working = true;
			while (working)
			{
				String data = input.readLine();
				synchronized(this)
				{
					if (!running) return;
				}
				processData(data);
				synchronized(this)
				{
					working = running; 
				}
			}
		} 
		catch (IOException e) 
		{
			host.close();
			host.takeStringUpdate(
					new Update<String>(
							UpdateType.CONNECTIONERROR, 
							"Disconnected"
							));
		}
	}
	
	public void close()
	{
		synchronized(this)
		{
			running = false;
		}
	}
	
	private void processData(String data)
	{
		StringTokenizer tokenizer = new StringTokenizer(data);
		if (tokenizer.hasMoreTokens()) switch (tokenizer.nextToken())
		{
			case Protocol.UpdateType.type:
				processUpdateMessage(tokenizer);
				break;
			default:
				break;
		}
	}
	
	private void processUpdateMessage(StringTokenizer tokenizer)
	{
		while (tokenizer.hasMoreTokens())
		{
			String token = tokenizer.nextToken();
			if (tokenizer.hasMoreTokens()) switch (UpdateType.valueOf(Integer.parseInt(token)))
			{
				case STATUS:
					host.takeStringUpdate(
							new Update<String>(
									UpdateType.STATUS, 
									tokenizer.nextToken()
									));
					break;
				case LEFTWHEEL:
					host.takeIntegerUpdate(
							new Update<Integer>(
									UpdateType.LEFTWHEEL, 
									Integer.parseInt(tokenizer.nextToken())
									));
					break;
				case RIGHTWHEEL:
					host.takeIntegerUpdate(
							new Update<Integer>(
									UpdateType.RIGHTWHEEL, 
									Integer.parseInt(tokenizer.nextToken())
									));
					break;
				case LED1:
					host.takeIntegerUpdate(
							new Update<Integer>(
									UpdateType.LED1, 
									Integer.parseInt(tokenizer.nextToken())
									));
					break;
				case LED2:
					host.takeIntegerUpdate(
							new Update<Integer>(
									UpdateType.LED2, 
									Integer.parseInt(tokenizer.nextToken())
									));
					break;
				case BUZZER:
					host.takeIntegerUpdate(
							new Update<Integer>(
									UpdateType.BUZZER, 
									Integer.parseInt(tokenizer.nextToken())
									));
					break;
				case SLEEP:
					host.takeIntegerUpdate(
							new Update<Integer>(
									UpdateType.SLEEP, 
									Integer.parseInt(tokenizer.nextToken())
									));
					break;
				case WHEELCONTROL:
					host.takeIntegerUpdate(
							new Update<Integer>(
									UpdateType.WHEELCONTROL, 
									Integer.parseInt(tokenizer.nextToken())
									));
					break;
				case COLORLANELEFTSENSOR:
					host.takeIntegerUpdate(
							new Update<Integer>(
									UpdateType.COLORLANELEFTSENSOR, 
									Integer.parseInt(tokenizer.nextToken())
									));
					break;
				case COLORLANERIGHTSENSOR:
					host.takeIntegerUpdate(
							new Update<Integer>(
									UpdateType.COLORLANERIGHTSENSOR, 
									Integer.parseInt(tokenizer.nextToken())
									));
					break;
				case SIDEEXITLEFTSENSOR:
					host.takeIntegerUpdate(
							new Update<Integer>(
									UpdateType.SIDEEXITLEFTSENSOR,
									Integer.parseInt(tokenizer.nextToken())
									));
					break;
				case SIDEEXITRIGHTSENSOR:
					host.takeIntegerUpdate(
							new Update<Integer>(
									UpdateType.SIDEEXITRIGHTSENSOR,
									Integer.parseInt(tokenizer.nextToken())
									));
					break;
				default:
					break;
			}
		}
		
	}
}
